import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { NzTreeFlatDataSource, NzTreeFlattener } from 'ng-zorro-antd/tree-view';
import { SelectionModel } from '@angular/cdk/collections';
import { FlatTreeControl } from '@angular/cdk/tree';
import { Menu, MenuPermission, SysroleMenu } from 'src/app/domain/menu';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { NzMessageService } from 'ng-zorro-antd/message';
import { EmployeeSearchComponent } from 'src/app/share/employee-search/employee-search.component';
import { MenuSearchComponent } from 'src/app/share/menu-search/menu-search.component';
import { NzFormatEmitEvent } from 'ng-zorro-antd/tree';
import { SetModelPermissionComponent } from 'src/app/share/set-model-permission/set-model-permission.component';
import { PermissionSelectComponent } from 'src/app/share/permission-select/permission-select.component';
import { SetDataPermissionComponent } from 'src/app/share/set-data-permission/set-data-permission.component';
import { SysroleSearchComponent } from 'src/app/share/sysrole-search/sysrole-search.component';
import { SparrowService } from 'src/app/service/sparrow.service';
import { Sysrole, UserSysrole } from 'src/app/domain/sparrow';
import { MenuService } from 'sparrow-permission-lib';

interface TreeNode {
  me: Menu;
  children?: TreeNode[];
}

interface FlatNode {
  expandable: boolean;
  me: Menu;
  level: number;
  includeSubMenu?: boolean;
}

@Component({
  selector: 'app-menu',
  templateUrl: './menu.component.html',
  styleUrls: ['./menu.component.css'],
})
export class MenuComponent implements OnInit {
  constructor(
    private menuService: MenuService,
    private router: Router,
    private fb: FormBuilder,
    private message: NzMessageService,
    private sparrowService: SparrowService
  ) {}
  includeSubMenu: boolean = false;

  private transformer = (node: TreeNode, level: number) => {
    const existingNode = this.nestedNodeMap.get(node);
    const flatNode =
      existingNode && existingNode.me.id === node.me.id
        ? existingNode
        : {
            expandable: !!node.children && node.children.length > 0,
            me: node.me,
            level,
            // disabled: !!node.disabled
          };
    this.flatNodeMap.set(flatNode, node);
    this.nestedNodeMap.set(node, flatNode);
    return flatNode;
  };

  selectListSelection = new SelectionModel<FlatNode>(false);

  treeControl = new FlatTreeControl<FlatNode>(
    (node: { level: any }) => node.level,
    (node: { expandable: any }) => node.expandable
  );
  treeFlattener = new NzTreeFlattener(
    this.transformer,
    (node) => node.level,
    (node) => node.expandable,
    (node) => node.children
  );

  dataSource = new NzTreeFlatDataSource(this.treeControl, this.treeFlattener);

  modelName?: string;

  nodes: any;
  nzEvent(event: NzFormatEmitEvent) {
    console.log(event);
  }

  ngOnInit(): void {
    this.menuService
      .getTree('MENU', undefined, undefined, 'root')
      .subscribe((res: any) => {
        this.nodes = res.children;
        this.nodes;
        this.dataSource.setData(res.children);
      });
  }

  hasChild = (_: number, node: FlatNode) => node.expandable;
  hasNoContent = (_: number, node: FlatNode) => node.me?.id === undefined;
  trackBy = (_: number, node: FlatNode) => `${node.me?.id}-${node.me?.name}`;

  // for checkbox tree
  flatNodeMap = new Map<FlatNode, TreeNode>();
  nestedNodeMap = new Map<TreeNode, FlatNode>();
  checklistSelection = new SelectionModel<FlatNode>(true);

  descendantsAllSelected(node: FlatNode): boolean {
    const descendants = this.treeControl.getDescendants(node);
    return (
      descendants.length > 0 &&
      descendants.every((child) => this.checklistSelection.isSelected(child))
    );
  }

  descendantsPartiallySelected(node: FlatNode): boolean {
    const descendants = this.treeControl.getDescendants(node);
    const result = descendants.some((child) =>
      this.checklistSelection.isSelected(child)
    );
    return result && !this.descendantsAllSelected(node);
  }

  leafItemSelectionToggle(node: FlatNode): void {
    this.checklistSelection.toggle(node);
    this.checkAllParentsSelection(node);
  }

  itemSelectionToggle(node: FlatNode): void {
    this.checklistSelection.toggle(node);
    const descendants = this.treeControl.getDescendants(node);
    this.checklistSelection.isSelected(node)
      ? this.checklistSelection.select(...descendants)
      : this.checklistSelection.deselect(...descendants);

    descendants.forEach((child) => this.checklistSelection.isSelected(child));
    this.checkAllParentsSelection(node);
  }

  checkAllParentsSelection(node: FlatNode): void {
    let parent: FlatNode | null = this.getParentNode(node);
    while (parent) {
      this.checkRootNodeSelection(parent);
      parent = this.getParentNode(parent);
    }
  }

  checkRootNodeSelection(node: FlatNode): void {
    const nodeSelected = this.checklistSelection.isSelected(node);
    const descendants = this.treeControl.getDescendants(node);
    const descAllSelected =
      descendants.length > 0 &&
      descendants.every((child) => this.checklistSelection.isSelected(child));
    if (nodeSelected && !descAllSelected) {
      this.checklistSelection.deselect(node);
    } else if (!nodeSelected && descAllSelected) {
      this.checklistSelection.select(node);
    }
  }

  getParentNode(node: FlatNode): FlatNode | null {
    const currentLevel = node.level;

    if (currentLevel < 1) {
      return null;
    }

    const startIndex = this.treeControl.dataNodes.indexOf(node) - 1;

    for (let i = startIndex; i >= 0; i--) {
      const currentNode = this.treeControl.dataNodes[i];

      if (currentNode.level < currentLevel) {
        return currentNode;
      }
    }
    return null;
  }

  sysroleMenus?: any[];
  onNodeSelect(node: FlatNode) {
    this.selectListSelection.toggle(node);
    if (this.selectListSelection.isSelected(node)) {
      this.menuService
        .getPermissions1(node.me.id!, 'SYSROLE')
        .subscribe((res) => {
          this.sysroleMenus = res;
        });
    } else {
      this.sysroleMenus = [];
    }
  }

  delOrganization() {
    console.log(this.checklistSelection.selected);
    const ids$: any = this.checklistSelection.selected.map(s => s.me.id);
    this.menuService.delete5(ids$).subscribe(
      res => {
        this.ngOnInit()
      },
      err => {
        console.log(err)
        this.message.create("error", "失败" + err.error.error)
      });
  }

  onClose(): void {
    console.log('tag was closed.');
  }

  onChange(value: string): void {
    console.log(value);
  }

  setModelPermission() {
    this.router.navigateByUrl(
      this.router.createUrlTree([
        '/modelPermission',
        { ids: JSON.stringify(this.modelName?.split(',')) },
      ])
    );
  }

  setDataPermission() {
    console.log(this.selectListSelection.selected);
    const dataIds$ = this.selectListSelection.selected.map((sel) => sel.me.id);
    this.router.navigateByUrl(
      this.router.createUrlTree([
        '/dataPermission',
        {
          ids: JSON.stringify(this.modelName?.split(',')),
          dataIds: JSON.stringify(dataIds$),
        },
      ])
    );
  }

  // for new organization

  isNewVisible: boolean = false;
  validateForm!: FormGroup;

  @ViewChild(MenuSearchComponent) employeeSearch!: MenuSearchComponent;

  submitForm() {
    const parents$ = this.employeeSearch.selectListSelection.selected.map(
      (s) => s.me.id
    );
    // console.log(this.organizationSearch.checklistSelection.selected.map(s=> {return {code:s.me.code,id:s.me.id}}),parents$.filter(p=> p.code === "0000").length>0)

    if (!this.validateForm.valid) {
      // console.log(this.validateForm.)
      for (const i in this.validateForm.controls) {
        if (this.validateForm.controls.hasOwnProperty(i)) {
          this.validateForm.controls[i].markAsDirty();
          this.validateForm.controls[i].updateValueAndValidity();
          console.log(i);
        }
      }
    } else {
      let menu: any = this.validateForm.value;
      console.log(menu);
      if(menu.id===undefined){
        if (parents$.filter((p) => p === '0000').length > 0) {
          // role.parentId=null
        } else {
          parents$
            .filter((p) => p != '0000')
            .forEach((f) => {
              menu.parentId = f;
            });
        }

        this.menuService.save(menu).subscribe((res) => {
          this.isNewVisible = false;
          this.ngOnInit();
        });
      }else{
        let id= menu.id
        console.log(this.selectListSelection.selected)
        menu.id = undefined
        if(menu.code === this.selectListSelection.selected[0].me.code!){
          menu.code=undefined
        }
        this.menuService.update6(id, menu).subscribe((res:any)=>{
          this.message.success('更新成功！')
          this.selectListSelection.selected[0].me = res
          this.isNewVisible = false;
        })
      }

    }
  }

  showNewModal(menu: Menu | null) {
    if (menu === null) {
      this.validateForm = this.fb.group({
        name: [null, [Validators.required]],
        code: [null, [Validators.required]],
        url: [null, [Validators.required]],
        icon: [null, [Validators.nullValidator]],
      });
    } else {
      this.validateForm = this.fb.group({
        name: [menu.name, [Validators.required]],
        code: [menu.code, [Validators.required]],
        url: [menu.url, [Validators.required]],
        id: [menu.id, [Validators.required]],
        icon: [menu.icon, [Validators.nullValidator]],
      });
    }
    this.isNewVisible = true;
  }

  validatePermissionForm!: FormGroup;
  isPermissionVisible: boolean = false;
  operationType!: string;
  showPermissionModal(sysrole: FlatNode | null): void {
    if (sysrole !== null) {
      this.selectListSelection.clear();
      this.selectListSelection.select(sysrole);
    }
    this.isPermissionVisible = true;
  }

  handlePermissionCancel(): void {
    console.log('Button cancel clicked!');
    this.isPermissionVisible = false;
  }

  @ViewChild(SysroleSearchComponent)
  sysroleSearchComponent!: SysroleSearchComponent;
  submitPermissionForm(): void {
    console.log(this.selectListSelection.selected);
    this.checklistSelection.selected.forEach((menu) => {
      this.menuService
        .addPermission1(
          menu.me.id!,
          'SYSROLE',
          this.sysroleSearchComponent.selectedUser!.map(
            (sysrole) => sysrole.id
          ),
          'response'
        )
        .subscribe((res) => {
          if (res.status === 204) {
          } else {
            this.message.error('授权失败！');
          }
        });
    });
    this.isPermissionVisible = false;
  }

  onSysroleRemove(sysroleId: any, e: Event) {
    this.menuService
      .delPermission(
        this.selectListSelection.selected[0].me.id!,
        'SYSROLE',
        [sysroleId],
        'response'
      )
      .subscribe((res) => {
        if (res.status === 204) {
          this.message.success('取消成功！');
        }
      });
  }

  up(node: any) {
    console.log(node);
  }

  down(node: any) {}

  // @ViewChild('nameInput') someInput: ElementRef;
  @ViewChild(SetModelPermissionComponent)
  setModelPermissionComponent!: SetModelPermissionComponent;
  isVisibleForSetPermission: boolean = false;
  showSetPermissionModal() {
    this.isVisibleForSetPermission = true;
    setTimeout(() => {
      this.setModelPermissionComponent.models = [];
      this.setModelPermissionComponent.models.push({
        name: 'cn.sparrow.model.permission.Menu',
        nameTxt: '菜单',
      });
    });
  }

  saveModelPermission() {
    this.setModelPermissionComponent.addPermission();
    this.isVisibleForSetPermission = false;
  }

  isVisibleForSetDataPermission: boolean = false;
  @ViewChild(SetDataPermissionComponent)
  setDataPermissionComponent!: SetDataPermissionComponent;
  showSetDataPermissionModal() {
    this.isVisibleForSetDataPermission = true;
    setTimeout(() => {
      const dataIds$: any[] = this.selectListSelection.selected.map(
        (sel) => sel.me.id
      );
      this.setDataPermissionComponent.dataIds = [];
      this.setDataPermissionComponent.dataIds.push(...dataIds$);
      this.setDataPermissionComponent.models.push({
        name: 'cn.sparrow.model.permission.Menu',
        nameTxt: '菜单',
      });
    });
  }

  saveDataPermission() {
    this.setDataPermissionComponent.addPermission();
    this.isVisibleForSetDataPermission = false;
  }

  handleCancel() {
    this.isNewVisible = false;
    this.isVisibleForSetPermission = false;
    this.isVisibleForSetDataPermission = false;
  }

  moveUp(node: FlatNode) {}

  moveDown(node: FlatNode) {}
}
